from __future__ import division
import sys,os,time,datetime
from src.Equipments.LockIn import SR830
from src.Equipments.RFGenerator import E8257D
from src.Equipments.multimeter import AgilentMulti
from src.Equipments.gaussmeter import Lakeshore455
from src.Equipments.EDMR_magnet import EDMRmagnet

from src.Physics.Tools import *
from src.Data.DataStructure import Data

import numpy as np
import matplotlib.pyplot as plt

import matplotlib.gridspec as gridspec

User="PierreAndre"

home_path=os.getcwd()+os.sep#Current path to this program
sys.path.append(home_path+"src"+os.sep)
data_path=home_path+"Users"+os.sep+User+os.sep+"data"+os.sep#For saving later on data
#print data_path

#########################################################
### Parameters - Sweeping settings
#########################################################
Field_unit="gauss"
Field_min=-10 #gauss
Field_max=10 #gauss
Field_resolution=0.5#0.4 gauss

field_table=np.arange(Field_min,Field_max+Field_resolution,Field_resolution)

number_of_points=field_table.size #Total number of points
Field_step=np.abs(Field_max-Field_min)/number_of_points
head_sentence="Scan between %d "+Field_unit+" and %d "+Field_unit+" at %d "+Field_unit+"/min: %d points"
print head_sentence %(Field_min,Field_max,Field_step,number_of_points)

#If standalone without anything connected->True
test=False 
doPrintPoints=False
recording={}
recording['Temperature']=False
recording['Field']=True
recording['Lockin-X']=True		#Always True
recording['Lockin-Y']=True		#Always True
recording['Lockin-Name']="Sample 1"
recording['Lockin2-X']=True		#Always True
recording['Lockin2-Y']=True		#Always True
recording['Lockin2-Name']="Sample 2"
recording['Lockin3-X']=False	#Always True
recording['Lockin3-Y']=False		#Always True
recording['Lockin3-Name']="Sample 3"
recording['Field command']=True	#Always True
#########################################################
#########################################################



#########################################################
### Parameters - Data saving
#########################################################
#Calculating the number of columns necessary
number_of_columns=0
for i in recording:
	if recording[i]==True:
		number_of_columns+=1
		
data=Data(given_name="SiP_n2_n1_n6",
		path=data_path,
		comments="bias:1.5V",
		rows=number_of_points,
		columns=number_of_columns,#Field, A channel
		light=7, #V
		temperature=5,#K
		scan_mode="field",
		phase=0,#in degree
		modulation_frequency=4.013,#in kHz
		modulation_amplitude=3,#in V
		receiver_mode=2,
		receiver_gain=1.5, #Or bias EDMR in V
		time_constant=0.3, #in s
		frequency=200,#MHz
		power=0,#dBm
		picture_saving_format='eps',
		user=User)
data.step=0 #Initial value
data.data[:,0]=field_table
#########################################################
#########################################################

#Minimum waiting time = about 300 ms (plot time is limitant)
waiting_time=2*data.time_constant*1000	#ms, Waiting time for each point

#########################################################
### Parameters - Magnet
#########################################################
magnet=EDMRmagnet(test)
#########################################################
#########################################################

#########################################################
### Parameters - Gaussmeter
#########################################################
if recording['Field']==True:
	gaussmeter=Lakeshore455("GPIB0::6::INSTR",test)
#########################################################
#########################################################

#########################################################
### Parameters - Lockin
#########################################################
lockin=SR830("GPIB0::7::INSTR",test)
lockin.Reset_Memory()
#lockin.Set_InterExter_Mode(1) #1 for internal mode, 2 for external mode (generated by RF-gen)
lockin.Set_Time_Constant(data.time_constant)
lockin.Set_Harm(data.receiver_mode)  #number of harmonics

nlockin=1
if recording['Lockin2-X'] == True:	
	lockin2=SR830("GPIB0::8::INSTR",test)
	lockin2.Reset_Memory()
	#lockin2.Set_InterExter_Mode(2) #1 for internal mode, 2 for external mode (generated by RF-gen)
	lockin2.Set_Time_Constant(data.time_constant)
	lockin2.Set_Harm(data.receiver_mode)  #number of harmonics
	nlockin+=1
	
if recording['Lockin3-X'] == True:	
	lockin3=SR830("GPIB0::9::INSTR",test)
	lockin3.Reset_Memory()
	#lockin3.Set_InterExter_Mode(2) #1 for internal mode, 2 for external mode (generated by RF-gen)
	lockin3.Set_Time_Constant(data.time_constant)
	lockin3.Set_Harm(data.receiver_mode)  #number of harmonics
	nlockin+=1

#########################################################
#########################################################


#########################################################
### Parameters - RF setup
#########################################################
#RF=E8257D("GPIB0::10::INSTR","FM",test)
#RF.Set_Modulation(5232,100)	#Frequency Hz, Modulation deviation kHz / amplitude dB
#RF.Set_Modulation_Output(False,False)	#Modulation On = True, LFOutput On = True
#RF.Set_Power(3)	#dBm
#RF.Set_Frequency(frequency_start)
#RF.Set_Output_ONOFF(True)
#########################################################
#########################################################


#########################################################
### Measure function
#########################################################
def DoMeasure(arg):
	#Change frequency
	#frequency=frequency_start+i*(frequency_stop-frequency_start)/(number_of_points-1)
	#RF.Set_Frequency(frequency)#MHz
	#data.data[i,0]=frequency
	ti=time.time()
	
	# For each point (except last one)
	if data.step <number_of_points-1:
		X,Y=lockin.Read_XY()
		data.data[data.step,1]=X
		data.data[data.step,2]=Y
		
		if recording['Lockin2-X'] == True:
			X2,Y2=lockin2.Read_XY()
			data.data[data.step,3]=X2
			data.data[data.step,4]=Y2	
	
		if recording['Lockin3-X'] == True:
			X3,Y3=lockin3.Read_XY()
			data.data[data.step,5]=X3
			data.data[data.step,6]=Y3
		
		#Optional recordings
		if recording['Field']==True:
			data.data[data.step,index_Field]=gaussmeter.Measure_Field()/1000
		if recording['Temperature']==True:
			data.data[data.step,index_Temperature]=thermometer.Measure_Temperature()
		
		#Console print
		if doPrintPoints:
			print "Step",data.step,"B0 = ",data.data[data.step,0]," mT, X = ",X,"V, Y = ",Y,"V"
			if recording['Lockin2-X'] == True:
				lockin2print = ", X2 = ", X2, "V, Y2 = ",Y2, "V"
			else:
				lockin2print = ""
				
			if recording['Lockin3-X'] == True:
				lockin3print = ", X3 = ", X3, "V, Y3 = ",Y3, "V"
			else:
				lockin3print = ""
				
			if recording['Field']==True:
				print "Step",data.step,"B0 = ",data.data[data.step,0],"Measured B0 =", data.data[data.step,index_Field], "mT, X = ",X,"V, Y = ",Y,"V",lockin2print,lockin3print
			else:
				print "Step",data.step,"B0 = ",data.data[data.step,0], " G, X = ",X,"V, Y = ",Y,"V",lockin2print,lockin3print
		
		#print from time to time the remaining time
		if data.internal_time_counter==30:
			remaining_time=(number_of_points-(data.step+1))*waiting_time
			data.Save_data()
			Print_flush("Remaining time: "+str(datetime.timedelta(seconds=remaining_time)))
			data.internal_time_counter=1
		
		data.step+=1
		data.internal_time_counter+=1
		#Update field
		magnet.SetMagneticField(data.data[data.step,0], Field_unit)
	
	# For last point
	elif data.step == number_of_points-1:
		X,Y=lockin.Read_XY()
		data.data[data.step,1]=X
		data.data[data.step,2]=Y
		
		if recording['Lockin2-X'] == True:
			X2,Y2=lockin2.Read_XY()
			data.data[data.step,3]=X2
			data.data[data.step,4]=Y2	
	
		if recording['Lockin3-X'] == True:
			X3,Y3=lockin3.Read_XY()
			data.data[data.step,5]=X3
			data.data[data.step,6]=Y3
		
		#Optional recordings
		if recording['Field']==True:
			data.data[data.step,index_Field]=gaussmeter.Measure_Field()/10000
		if recording['Temperature']==True:
			data.data[data.step,index_Temperature]=thermometer.Measure_Temperature()

		
		data.Save_data()
		#has to be after data.Save_data because that method fill the self.full_saving_path value
		plt.savefig(data.full_saving_path+'.'+data.picture_saving_format,format=data.picture_saving_format)

		data.step+=1
		print "Data acquired and saved."
		magnet.CloseRessource()
		
	else:
		pass
	
	DoTime=time.time()-ti
	if waiting_time-DoTime*1000<=0:
		DeltaTDo=waiting_time
	else:
		DeltaTDo=waiting_time-DoTime*1000
	TimerDo.interval=DeltaTDo
#########################################################
#########################################################



#########################################################
### Plotting functions
#########################################################
fig = plt.figure(1)

gs1 = gridspec.GridSpec(2, nlockin)

## New setup

#Dirty artefac to reorder graphs
if recording['Lockin2-X'] == True:
	if recording['Lockin3-X'] == True:
		graph_order=[0,3,1,4,2,5]
	else:
		graph_order=[0,2,1,3]
else:
	graph_order=[0,1]
	
ax_list=[fig.add_subplot(gs1[graph_order[0]]),fig.add_subplot(gs1[graph_order[1]])]
ax_list[0].set_title(recording['Lockin-Name'])

ax_list[0].set_ylabel("EDMR in-phase (V)")
ax_list[1].set_ylabel("EDMR out-phase (V)")

if recording['Lockin2-X'] == True:
	ax_list.append(fig.add_subplot(gs1[graph_order[2]]))
	ax_list.append(fig.add_subplot(gs1[graph_order[3]]))
	ax_list[2].set_title(recording['Lockin2-Name'])
if recording['Lockin3-X'] == True:
	ax_list.append(fig.add_subplot(gs1[graph_order[4]]))
	ax_list.append(fig.add_subplot(gs1[graph_order[5]]))
	ax_list[4].set_title(recording['Lockin3-Name'])

for ax_i in ax_list:
	ax_i.grid(True)
	ax_i.axis([0,1,0,1])

lines_list=[ax_list[0].plot([0,1],[0,1],'o-k'),ax_list[1].plot([0,1],[0,1],'o-r')]
if recording['Lockin2-X'] == True:
	lines_list.append(ax_list[2].plot([0,1],[0,1],'o-k'))
	lines_list.append(ax_list[3].plot([0,1],[0,1],'o-r'))
if recording['Lockin3-X'] == True:
	lines_list.append(ax_list[4].plot([0,1],[0,1],'o-k'))
	lines_list.append(ax_list[5].plot([0,1],[0,1],'o-r'))


manager = plt.get_current_fig_manager()

def RealtimePloter(arg):
	global values
	ti=time.time()
	if data.step>1:
		for i in range(len(lines_list)):
			lines_list[i][0].set_data(data.data[0:data.step,0],data.data[0:data.step,1+i])
			ax_list[i].axis([data.data[0:data.step,0].min(),data.data[0:data.step,0].max(),data.data[0:data.step,1+i].min(),data.data[0:data.step,1+i].max()])
		manager.canvas.draw()
	PlotTime=time.time()-ti
	if waiting_time-PlotTime*1000<=0:
		DeltaTPlot=waiting_time
	else:
		DeltaTPlot=waiting_time-PlotTime*1000
	TimerPlot.interval=DeltaTPlot
#########################################################
#########################################################


#########################################################
### Measure initialization
#########################################################

#Reseting the locking memory
lockin.Reset_Memory()

if recording['Lockin2-X'] == True:	
	lockin2.Reset_Memory()
	
if recording['Lockin3-X'] == True:	
	lockin3.Reset_Memory()

#Start the magnet
magnet.OpenRessource()
magnet.SetMagneticField(data.data[data.step,0], "gauss")
if not test:
	time.sleep(6) #Time to stabilize the magnetic field

data.internal_time_counter=0

#Preparing the indexes
afterindex = 3
if recording['Lockin2-X'] == True:
	afterindex += 2
if recording['Lockin3-X'] == True:
	afterindex += 2
	
if recording['Field']==True:
	index_Field = afterindex
	index_Temperature = afterindex + 1
elif recording['Field']==False:
	index_Temperature= afterindex

#########################################################
#########################################################


#########################################################
### Measure loop
#########################################################
TimerPlot = fig.canvas.new_timer(interval=waiting_time)
TimerPlot.add_callback(RealtimePloter, ())
TimerDo = fig.canvas.new_timer(interval=waiting_time)
TimerDo.add_callback(DoMeasure, ())
TimerPlot.start()
TimerDo.start()

plt.show()	
magnet.CloseRessource()
#########################################################
### Measure loop end
#########################################################


